<template>
    <el-container class="container">
        <div class="searchbar" v-if="isMobile">
            <div style="display: flex; justify-content: space-between">
                <div class="breadcrumb">
                    <el-breadcrumb separator="/">
                        <el-breadcrumb-item :to="{ path: '/' }">
                            <el-icon><House /></el-icon>
                        </el-breadcrumb-item>
                        <el-breadcrumb-item :to="{ path: '/search/none/none/none' }">EcDNA Search</el-breadcrumb-item>
                    </el-breadcrumb>
                </div>
                <el-button type="primary" style="margin-left: 16px" @click="drawer = true">Search Conditions</el-button>
            </div>
            <el-drawer v-model="drawer" direction="ltr" size="50%" v-if="drawer">
                <EsSearchBar :modelValue="inputVal" :tabValue="tabValue" @tab="onTabChange" @select="onSelectChange" />
                <!-- <KeepAlive>
                    <SearchColumn 
                        :searchItems="searchItems" 
                        :updateTable="updateTable" 
                        :initSelectedValues="initSelectedValues"
                        page="ecDNA"
                        />
                </KeepAlive>    -->
            </el-drawer>
        </div>
        <div class="searchbar" v-else>
            <div class="breadcrumb">
                <el-breadcrumb separator="/">
                    <el-breadcrumb-item :to="{ path: '/' }">
                        <el-icon><House /></el-icon>
                    </el-breadcrumb-item>
                    <el-breadcrumb-item :to="{ path: '/search/none/none/none' }">EcDNA Search</el-breadcrumb-item>
                </el-breadcrumb>
            </div>
            <KeepAlive>
                <EsSearchBar 
                    :modelValue="inputVal" 
                    :tabValue="tabValue" 
                    @tab="onTabChange" 
                    @select="onSelectChange" 
                    />
            </KeepAlive>
        </div>
        <div  v-if="showChart">
            <el-divider content-position="left" class="divider">Statistics Charts</el-divider>
            <StatsChart      
                :flatChartData="chartData.flat"
                :nestedChartData="chartData.nested"
                :verticalChartData="chartData.vertical"
            />
        </div>
        <el-divider content-position="left" class="divider">Search Result</el-divider>
        <div class="table-container" ref="tableWrapper">
            <el-table-v2
                v-model:expanded-row-keys="expandedRowKeys"
                v-model:sort-state="sortState"
                :columns="columns"
                :data="tableData"
                :height="tableHeight"
                :width="tableWidth"
                stripe
                @column-sort="handleSortChange"
                row-key="uuid"
                v-loading="loading"
                @expanded-rows-change="onExpandedRowsChange"
                scrollbar-always-on
                expand-column-key="ecDNA"
            ></el-table-v2>
        </div>
        <div class="pagination-container">
            <el-pagination
                v-model:current-page="currentPage"
                :page-size="currentPageSize"
                background
                :page-sizes="[10, 20, 50, 100]"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
            />
        </div>
    </el-container>
</template>

<script lang="ts" setup name="Search">
    import { ref, computed, watch, onBeforeMount, onActivated, nextTick, onBeforeUnmount, reactive, onMounted } from 'vue';
    import { useRouter, useRoute } from 'vue-router';
    import { ElMessage, ElLoading, TableV2SortOrder } from 'element-plus';
    import EsSearchBar from '@/components/EsSearchBar.vue';
    import StatsChart from './StatsChart.vue';
    import { get, post } from '../../axios/api';
    import { getColumns } from './commonConfig';
    import { groupDict } from '@/common/util';

    // 定义缺失的类型
    type SortState = Record<string, TableV2SortOrder>;
    type SortBy = { key: string; order?: TableV2SortOrder };

    interface ChartData {
        flat: { categories: string[]; values: number[] };
        nested: { categories: string[]; series: any[] };
        vertical: { categories: string[]; series: any[] };
    }

    // 声明数据属性
    const tableHeight = 600;
    const tableWidth = computed(() => {
        return columns.value.reduce((sum, col) => {
            // 优先取 width，其次取 minWidth，最后 0
            const w = (col.width ?? col.minWidth ?? 0) as number;
            return sum + w;
        }, 0);
    });

    const expandedRowKeys = ref<string[]>([]); // v-model 绑定展开行 keys

    let inputVal: any = ref('');
    const tabValue = ref<'Gene' | 'Cellline' | 'OncotreeLineage' | 'SampleType'>('Cellline')
    function onExpandedRowsChange(keys: string[]) {
        expandedRowKeys.value = keys;
    }

    const tableWrapper = ref<HTMLElement | null>(null);

    const columns = computed(() => getColumns(showCellLine.value, checkDetail));

    let tableData = ref([]);
    let total = ref(0);
    let currentPage = ref(1);
    let currentPageSize = ref(10);
    const router = useRouter();
    const route = useRoute();
    let isSorted = ref(false);
    let sortedProp = ref('final_score');
    let sortedOrder = ref('desc');
    let showCellLine = ref(true);
    const initSortedBy = 'final_score';
    const initSortedOrder = 'desc';
    let isMobile = ref(window.innerWidth <= 768);
    const drawer = ref(false);
    let loadingInstance: any = null;
    const loading = ref(false);

    const sortState = ref<SortState>({
        final: TableV2SortOrder.DESC
    });

    const searchParams = reactive({
        Gene: '',
        Cellline: '',
        OncotreeLineage: '',
        SampleType: ''
    })

    const chartData = reactive<ChartData>({
        flat: { categories: [], values: [] },
        nested: { categories: [], series: [] },
        vertical: {categories: [], series: []},
    })

    const showChart = computed(() => {
        return chartData.flat.categories.length > 0 || chartData.nested.categories.length > 0
    })


    async function search(page=1, pageSize=10, sort_by:any, sort_order:any) {
        loadingInstance = ElLoading.service({ fullscreen: true });
        loading.value = true;
        try {
            const res: any = await post('/get_data/', {
                page,
                sort_by,
                sort_order,
                page_size: pageSize,
                showCellLine: showCellLine.value,
                params: {...searchParams},
            })
            if (res && res.success) { 
                tableData.value = res.list
                currentPage.value = res.page;
                total.value = res.total;
                loadingInstance.close();
                loading.value = false;
            }
        } catch (error: any) {
            loadingInstance.close();
            loading.value = false;
            ElMessage({
                message: error,
                type: 'error'
            });
        }

        if (searchParams.Gene) {
            try {
                const chartRes: any = await post('get_stats_v2/', {params: {...searchParams}, sort_by,
                    sort_order, showCellLine:showCellLine.value})
                const verticalChartRes :any = await get('gene_cnv_proportions', {gene: searchParams.Gene})
                if (chartRes && chartRes.success) {
                    chartData.flat = chartRes.flat_chart_data
                    chartData.nested = chartRes.nested_chart_data
                }
                if (verticalChartRes && verticalChartRes.success) {
                    chartData.vertical = verticalChartRes
                }
            } catch (error: any) {
                ElMessage({
                    message: error,
                    type: 'error'
                });
            }
        } else {
            const vals = Object.values(searchParams) as string[]
            const allEmpty = vals.every(v => v === '' || v === undefined)
            if (allEmpty) {
                Object.assign(chartData, {
                    flat: { categories: [], values: [] },
                    nested: { categories: [], series: [] }
                })
                return
            } else {
                try {
                    const chartRes: any = await post('stats_by_param/', {params: {...searchParams}, sort_by,
                        sort_order, showCellLine: showCellLine.value,})
                    if (chartRes.success) {
                        chartData.flat = chartRes.flat_chart_data
                        // 不需要嵌套图
                        chartData.nested = { categories: [], series: [] }
                    }

                } catch (error: any) {
                    ElMessage({
                        message: error,
                        type: 'error'
                    });
                }
            }
        }
    }


    async function handleSortChange({ key, order }: SortBy) {
        loadingInstance = ElLoading.service({ fullscreen: true });
        loading.value = true;
        isSorted.value = true;

        let target: any = columns.value.find(ele => ele.key === key);
        sortedProp.value = target.dataKey;
        if (order) {
            sortState.value[key] = order;
            sortedOrder.value = order;
        } else {
            sortState.value = {};
            sortState.value[target.key] = TableV2SortOrder.DESC;
            sortedOrder.value = TableV2SortOrder.DESC;
        }

        search(currentPage.value, currentPageSize.value, sortedProp.value, sortedOrder.value)
    }

    async function handleCurrentChange(val: number) {
        currentPage.value = val;
        if (isSorted) {
            search(val, currentPageSize.value, sortedProp.value, sortedOrder.value);
        } else {
            search(val, currentPageSize.value, initSortedBy, initSortedOrder);
        }
    }

    async function handleSizeChange(val: number) {
        currentPageSize.value = val;
        if (isSorted) {
            search(currentPage.value, val, sortedProp.value, sortedOrder.value);
        } else {
            search(currentPage.value, val, initSortedBy, initSortedOrder);
        }
    }

    function checkDetail(row: any) {
        router.push({
            name: 'ecDetail',
            params: {
                filename: row.Filename,
                SampleType: row.SampleType ? row.SampleType : 'none',
                circ: row.AmpliconID,
                OncotreeLineage: row.OncotreeLineage,
                MajorTumorType: row.MajorTumorType,
                Cellline: row.Cellline ? row.Cellline : 'none'
            }
        });
    }

    function onSelectChange(event: any) {
        // 每次selectChange时都执行此方法，重置searchParams，并将新选择的项在此时赋值，search方法可以直接用
        const { tab, group, value } = event;
        Object.assign(searchParams, {
            Gene: '',
            Cellline: '',
            OncotreeLineage: '',
            SampleType: ''
        })

        if (tab === groupDict[group]) {
            // tab 本身就是要用的字段
            searchParams[tab as keyof typeof searchParams] = value
            tabValue.value = tab
        } else {
            // 否则用 group 指定的字段
            const key = groupDict[group] as keyof typeof searchParams
            searchParams[key] = value
        }
        inputVal.value = value
        currentPage.value = 1
        search(1, currentPageSize.value, sortedProp.value, sortedOrder.value)
    }

    function onTabChange(field: any) {
        const { type } = field;
        Object.assign(searchParams, {
            Gene: '',
            Cellline: '',
            OncotreeLineage: '',
            SampleType: ''
        })
        Object.assign(chartData, {
            flat: { categories: [], values: [] },
            nested: { categories: [], series: [] }
        })
        showCellLine.value = type === 'Cellline';
        tabValue.value = type
        const key = type as keyof typeof searchParams
        searchParams[key] = ''
        inputVal.value = ''
        search(currentPage.value, currentPageSize.value, sortedProp.value, sortedOrder.value)
    }

    onMounted(() => {
        loadingInstance = ElLoading.service({ fullscreen: true });
        loading.value = true;
        const p = route.params as any;
        if (p.Cellline && p.Cellline !== 'none') {
            searchParams.Cellline = p.Cellline;
            tabValue.value = 'Cellline';
            inputVal.value = p.Cellline;
        } else if (p.OncotreeLineage && p.OncotreeLineage !== 'none') {
            searchParams.OncotreeLineage = p.OncotreeLineage;
            inputVal.value = p.OncotreeLineage;
        } else if (p.SampleType && p.SampleType !== 'none') {
            searchParams.SampleType = p.SampleType;
            tabValue.value = 'SampleType';
            inputVal.value = p.SampleType;
        }
        search(currentPage.value, currentPageSize.value, initSortedBy, initSortedOrder);
    });
</script>

<style scoped>
    .breadcrumb {
        margin: 8px 0;
    }

    .table-container {
        width: 100%;
        margin: 10px 0px;
        display: flex;
        justify-content: center;
        border-radius: 4px;
        background-color: white;
        position: relative;
        overflow: hidden;
        scroll-behavior: auto;
    }

    .el-table-v2 {
        /* 确保表格自身滚动 */
        overflow: auto;
    }

    :deep(.el-divider__text) {
        background: rgb(245, 247, 249);
    }

    :deep(.el-table__body-wrapper, .el-table-v2 .el-virtual-list) {
        scroll-behavior: auto !important;
    }

    :deep(.el-table-v2__main) {
        overflow: auto !important;
        position: relative !important;
        /* height: 600px; */
    }

    :deep(.el-table) {
        border-radius: 4px;
    }

    .pagination-container {
        margin: 20px 10px;
        display: flex;
        justify-content: center;
    }
    :deep(.tissue) {
        cursor: pointer;
        color: dodgerblue;
    }

    :deep(a:hover) {
        color: rgb(24, 188, 146);
    }

    .container {
        width: 100%;
        display: flex;
        flex-direction: column;
    }

    @media screen and (max-width: 768px) {
        .container {
            width: 100%;
            display: flex;
            flex-wrap: wrap;
        }
    }

    .searchbar {
        width: 100%;
        display: block;
    }

    .stats-chart {
        margin-top: 20px;
    }
</style>